package ru.evga.billboard.graph;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.imageio.ImageIO;

import ru.evga.billboard.editor.behaviors.EditorContext;
import ru.evga.billboard.graph.preference.GraphSettings;


public class Background
    implements INode, ImageObserver
{
    private static final String IMAGE_FORMAT = "jpg";
    private BufferedImage img;
    private Rectangle2D.Double rectangle;
    private static final int CORNER_SIZE = 10;
    private static final Color CORNER_COLOR = new Color(0, 255, 0);
    private final GraphSettings preference;
    public enum Corner {
        RB, C
    };

    public Background(GraphSettings preference)
    {
        this.preference = preference; 
        rectangle = preference.background.getValue();
    }

    public Rectangle2D.Double getRectangle()
    {
        return rectangle == null ? new Rectangle2D.Double() : rectangle;
    }

    public void paint(Graphics2D g2, EditorContext context)
    {
        if (img == null)
        {
            return;
        }
        double zoom = context.getDrawPanel().getZoom();
        g2.drawImage(img, (int)(rectangle.getX() * zoom), (int)(rectangle.getY() * zoom),
            (int)(rectangle.getWidth() * zoom), (int)(rectangle.getHeight() * zoom), this);
        g2.setColor(CORNER_COLOR);
        Rectangle r = getRB(zoom);
        g2.fillRect((int)r.getX(), (int)r.getY(), (int)r.getWidth(), (int)r.getHeight());
    }

    public Corner getCorner(Point2D.Double p)
    {
        if (rectangle != null)
        {
            if (getRB(1).contains(p))
            {
                return Corner.RB;
            }
            else if (rectangle.contains(p))
            {
                return Corner.C;
            }
        }
        return null;
    }

    public void move(double dx, double dy, Corner corner)
    {
        if (corner == Corner.C)
        {
            double x = rectangle.getX() + dx;
            double y = rectangle.getY() + dy;
            rectangle.x = Math.max(0, x);
            rectangle.y = Math.max(0, y);
        }
        else if (corner == Corner.RB)
        {
            rectangle.width = Math.abs(rectangle.getWidth() + dx);
            rectangle.height = Math.abs(rectangle.getHeight() + dy);
        }
    }

    @Override
    public boolean imageUpdate(Image img, int infoflags, int x, int y, int w, int h)
    {
        return true;
    }

    private Rectangle getRB(double zoom)
    {
        if (rectangle == null)
        {
            return new Rectangle();
        }
        return new Rectangle((int)(rectangle.getX() * zoom) + (int)(rectangle.getWidth() * zoom)
            - CORNER_SIZE / 2, (int)(rectangle.getY() * zoom) + (int)(rectangle.getHeight() * zoom)
            - CORNER_SIZE / 2, CORNER_SIZE, CORNER_SIZE);
    }

    public byte [] getContentAsBytes()
    {
        if (img == null)
        {
            return new byte[0];
        }
        try
        {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ImageIO.write(img, IMAGE_FORMAT, bos);
            return bos.toByteArray();
        }
        catch (IOException e)
        {
            e.printStackTrace();
            return null;
        }
    }

    public void setContentFromStream(InputStream is)
    {
        try
        {
            img = ImageIO.read(is);
            rectangle = preference.background.getValue();

//            if (img != null)
//            {
//                rectangle = new Rectangle2D.Double(0, 0, img.getWidth(this), img.getHeight(this));
//            }
            is.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public void setContentFromBytes(byte [] data)
    {
        ByteArrayInputStream is = new ByteArrayInputStream(data);
        setContentFromStream(is);
    }
}
